﻿//===========================[ 7 / 6 / 2011 LVI ]=============================
//				Copyright c Vitaly Lyaschenko <SkyChameleon@gmail.com>
//								Source file
// Purpose: 
//=============================================================================
#include "cInput.h"
#include "cwLogger.h"

static HGLRC     g_hRC       = NULL;
static RECT      g_clipRect;

// буфер состояний кнопок мыши
byte cMouse::m_tempBuffer[40];

cMouse::cMouse(void) : m_hWnd(NULL),
    m_WheelDelta(0), m_WheelDeltaPrev(0), m_mouseWheel(0.0f),
    m_XposAbsolute(NULL),
    m_YposAbsolute(NULL),
    m_XposRelative(NULL),
    m_YposRelative(NULL),
    cursorVisible(false)
{
    GetClipCursor( &g_clipRect );
}

cMouse::~cMouse(void)
{

}

bool cMouse::attach( HWND hWnd )
{
    //ASSERT(hWnd);
    if (!hWnd) 
        return false;

    if (!this->m_hWnd)
    {
        RAWINPUTDEVICE rid[1] = {0};

        rid[0].usUsagePage = 1;
        rid[0].usUsage = 2;
        rid[0].dwFlags = 0;
        rid[0].hwndTarget = hWnd;

        if (!RegisterRawInputDevices(rid, 1, sizeof(rid[0])))
            return false;
        this->m_hWnd = hWnd;
    }

    if (!cursorVisible)
        hideCursor(false);

    pCurrButtonStates = buttonStates[0];
    pPrevButtonStates = buttonStates[1];

    memset(buttonStates, 0, sizeof(buttonStates));

    RECT rcClient;
    GetClientRect( m_hWnd, &rcClient);
    int width = ( rcClient.right - rcClient.left );
    int height = ( rcClient.bottom - rcClient.top );
    m_ptWindowCenterPos.x = width / 2;
    m_ptWindowCenterPos.y = height / 2;   

    int x = (GetSystemMetrics(SM_CXSCREEN) - width)  / 2;
    int y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;

    rcClient.left   = x;
    rcClient.right  = x + width;
    rcClient.top    = y;
    rcClient.bottom = y + height;
    
    SetCursorPos( x + width / 2, y + height / 2 );

   // ClipCursor(&rcClient);
    return true;
}

void cMouse::detach()
{
    if (!cursorVisible)
    {
        hideCursor(false);

        cursorVisible = false;
    }
    RECT rcClient;
    rcClient.left   = 0;
    rcClient.right  = GetSystemMetrics( SM_CXSCREEN );
    rcClient.top    = 0;
    rcClient.bottom = GetSystemMetrics( SM_CYSCREEN );

    ClipCursor( &g_clipRect );

    this->m_hWnd = 0;
}
///////////////////////////////////////////////////////////////////////////
// обработка mouse event
void cMouse::hMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    RAWINPUT *pRaw = NULL;
    UINT sizeBuf = 40;

    switch (msg)
    {
    case WM_INPUT:
        {
            GetRawInputData((HRAWINPUT)(lParam), RID_INPUT,
                m_tempBuffer, &sizeBuf, sizeof(RAWINPUTHEADER));

            pRaw = (RAWINPUT*)(m_tempBuffer);

            if ( pRaw->header.dwType == RIM_TYPEMOUSE )
            {
                if (pRaw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE)
                {
                    m_XposRelative += pRaw->data.mouse.lLastX;
                    m_YposRelative += pRaw->data.mouse.lLastY;
                }
            }
        } break;
    case WM_MOUSEMOVE:
        {
            m_XposAbsolute = (int)( (short)(LOWORD(lParam) ) );
            m_YposAbsolute = (int)( (short)(HIWORD(lParam) ) );
        } break;

    case WM_MOUSEWHEEL:
        m_WheelDelta += (int)( (int)wParam >> 16 );
        break;
    default:
        break;
    }
}

void cMouse::hideCursor( bool visible )
{
    ShowCursor( visible ? TRUE : FALSE );
}

void cMouse::setPosition(UINT x, UINT y)
{
    POINT pt = {x, y};

    if (ClientToScreen(m_hWnd, &pt))
    {
        SetCursorPos(pt.x, pt.y);

        m_XposAbsolute = x;
        m_YposAbsolute = y;

        m_XposRelative = 0.0f;
        m_YposRelative = 0.0f;
    }
}

void cMouse::getPosition( UINT& _x, UINT& _y )
{
    ASSERT(_x);
    ASSERT(_y);

    _x = m_XposAbsolute;
    _y = m_YposAbsolute;	
}

void cMouse::update()
{
    bool *pTempMouseStates = pPrevButtonStates;

    pPrevButtonStates = pCurrButtonStates;
    pCurrButtonStates = pTempMouseStates;

    pCurrButtonStates[0] = (GetKeyState(VK_LBUTTON) & 0x8000) ? true : false;
    pCurrButtonStates[1] = (GetKeyState(VK_RBUTTON) & 0x8000) ? true : false;
    pCurrButtonStates[2] = (GetKeyState(VK_MBUTTON) & 0x8000) ? true : false;
    
    // обновление скролинга мыши
    m_mouseWheel = (float)( m_WheelDelta - m_WheelDeltaPrev ) / (float)WHEEL_DELTA;
    m_WheelDeltaPrev = m_WheelDelta;
}
